package homework017;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * **需求一：**创建一个Student类，使用反射获取Student类的class对象，并打印
 * <p>
 * **需求二：**使用反射机制，打印Student类中所有的成员变量，并给变量赋值
 * <p>
 * **需求三：**使用反射机制，打印Student类中的所有成员方法，并执行Student的hashCode方法
 */
public class Main {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        // 1. 获取类的class对象
        Class aClass = Class.forName("homework017.Student");

        // 4. 创建Student对象
        Constructor constructor = aClass.getConstructor();

        // 使用newInstance来创建对象
        // 创建后的对象，要根据原来的类型，进行一个强制转换
        // 如果你这个对象是Student类型的，那么你就要强制转成Student
        // 这个操作不是必须的
        // 我们强转是为了，可以直接用对象访问它的成员
        Student student = (Student) constructor.newInstance();

        // 2. 获取变量
        // 2.1. 获取公共变量 getFiled()
        // 2.2. 获取私有变量 getDeclaredField()

        // 5. 获取所有成员方法
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());

//            if("setId".equals(method.getName())) {
//                method.invoke(student, "2");
//            }

            if ("hashCode".equals(method.getName())) {
                // invoke的结果，其实就是你调用的方法的返回值
                int invoke = (int) method.invoke(student);
                System.out.println("hashcode的返回值" + invoke);
            }
        }


        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field : declaredFields) {
            // 如果你打印的是一个field对象，那么其实是调用Field的toString方法
            System.out.println(field);

            // 如果打印getName,其实就是直接打印变量名称
            System.out.println(field.getName());

            // 3. 给变量赋值
            // 3.1 给公共变量赋值 filed.set(obj, "值");
            // 3.2 给私有变量赋值 filed.setAccessible(true) 暴力访问
            // 访问私有变量时，因为私有变量受到保护
            // 所以必须使用强制手段才能访问到
            field.setAccessible(true);

            // set方法接收两个参数
            // 参数一：一个对象，这个对象必须是我们反射那个类，或者是那个类的子类
            // 参数二：变量值
            field.set(student, "jack");
            System.out.println("赋值之后的变量值:" + field.get(student));
        }


    }

}
